/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */

package l1j.jrwz.server;

import static l1j.jrwz.server.Opcodes.C_OPCODE_ADDBUDDY;
import static l1j.jrwz.server.Opcodes.C_OPCODE_AMOUNT;
import static l1j.jrwz.server.Opcodes.C_OPCODE_ARROWATTACK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_ATTACK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_ATTR;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BANCLAN;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BANPARTY;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BOARD;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BOARDDELETE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BOARDNEXT;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BOARDREAD;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BOARDWRITE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BOOKMARK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BOOKMARKDELETE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_BUDDYLIST;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CAHTPARTY;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CALL;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHANGECHAR;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHANGEHEADING;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHANGEWARTIME;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHARACTERCONFIG;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHARRESET;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHAT;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHATGLOBAL;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHATWHISPER;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CHECKPK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CLAN;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CLIENTVERSION;
import static l1j.jrwz.server.Opcodes.C_OPCODE_COMMONCLICK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CREATECLAN;
import static l1j.jrwz.server.Opcodes.C_OPCODE_CREATEPARTY;
import static l1j.jrwz.server.Opcodes.C_OPCODE_DELBUDDY;
import static l1j.jrwz.server.Opcodes.C_OPCODE_DELETECHAR;
import static l1j.jrwz.server.Opcodes.C_OPCODE_DELETEINVENTORYITEM;
import static l1j.jrwz.server.Opcodes.C_OPCODE_DEPOSIT;
import static l1j.jrwz.server.Opcodes.C_OPCODE_DOOR;
import static l1j.jrwz.server.Opcodes.C_OPCODE_DRAWAL;
import static l1j.jrwz.server.Opcodes.C_OPCODE_DROPITEM;
import static l1j.jrwz.server.Opcodes.C_OPCODE_EMBLEM;
import static l1j.jrwz.server.Opcodes.C_OPCODE_ENTERPORTAL;
import static l1j.jrwz.server.Opcodes.C_OPCODE_EXCLUDE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_EXIT_GHOST;
import static l1j.jrwz.server.Opcodes.C_OPCODE_EXTCOMMAND;
import static l1j.jrwz.server.Opcodes.C_OPCODE_FIGHT;
import static l1j.jrwz.server.Opcodes.C_OPCODE_FISHCLICK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_FIX_WEAPON_LIST;
import static l1j.jrwz.server.Opcodes.C_OPCODE_GIVEITEM;
import static l1j.jrwz.server.Opcodes.C_OPCODE_HIRESOLDIER;
import static l1j.jrwz.server.Opcodes.C_OPCODE_JOINCLAN;
import static l1j.jrwz.server.Opcodes.C_OPCODE_KEEPALIVE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_LEAVECLANE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_LEAVEPARTY;
import static l1j.jrwz.server.Opcodes.C_OPCODE_LOGINPACKET;
import static l1j.jrwz.server.Opcodes.C_OPCODE_LOGINTOSERVER;
import static l1j.jrwz.server.Opcodes.C_OPCODE_LOGINTOSERVEROK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_MAIL;
import static l1j.jrwz.server.Opcodes.C_OPCODE_MOVECHAR;
import static l1j.jrwz.server.Opcodes.C_OPCODE_NEWCHAR;
import static l1j.jrwz.server.Opcodes.C_OPCODE_NPCACTION;
import static l1j.jrwz.server.Opcodes.C_OPCODE_NPCTALK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_PARTYLIST;
import static l1j.jrwz.server.Opcodes.C_OPCODE_PETMENU;
import static l1j.jrwz.server.Opcodes.C_OPCODE_PICKUPITEM;
import static l1j.jrwz.server.Opcodes.C_OPCODE_PLEDGE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_PRIVATESHOPLIST;
import static l1j.jrwz.server.Opcodes.C_OPCODE_PROPOSE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_QUITGAME;
import static l1j.jrwz.server.Opcodes.C_OPCODE_RANK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_RESTART;
import static l1j.jrwz.server.Opcodes.C_OPCODE_RESULT;
import static l1j.jrwz.server.Opcodes.C_OPCODE_RETURNTOLOGIN;
import static l1j.jrwz.server.Opcodes.C_OPCODE_SELECTLIST;
import static l1j.jrwz.server.Opcodes.C_OPCODE_SELECTTARGET;
import static l1j.jrwz.server.Opcodes.C_OPCODE_SENDLOCATION;
import static l1j.jrwz.server.Opcodes.C_OPCODE_SHIP;
import static l1j.jrwz.server.Opcodes.C_OPCODE_SHOP;
import static l1j.jrwz.server.Opcodes.C_OPCODE_SKILLBUY;
import static l1j.jrwz.server.Opcodes.C_OPCODE_SKILLBUYOK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_TAXRATE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_TELEPORT;
import static l1j.jrwz.server.Opcodes.C_OPCODE_TITLE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_TRADE;
import static l1j.jrwz.server.Opcodes.C_OPCODE_TRADEADDCANCEL;
import static l1j.jrwz.server.Opcodes.C_OPCODE_TRADEADDITEM;
import static l1j.jrwz.server.Opcodes.C_OPCODE_TRADEADDOK;
import static l1j.jrwz.server.Opcodes.C_OPCODE_USEITEM;
import static l1j.jrwz.server.Opcodes.C_OPCODE_USEPETITEM;
import static l1j.jrwz.server.Opcodes.C_OPCODE_USESKILL;
import static l1j.jrwz.server.Opcodes.C_OPCODE_WAR;
import static l1j.jrwz.server.Opcodes.C_OPCODE_WHO;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.jrwz.server.clientpackets.C_AddBookmark;
import l1j.jrwz.server.clientpackets.C_AddBuddy;
import l1j.jrwz.server.clientpackets.C_Amount;
import l1j.jrwz.server.clientpackets.C_Attack;
import l1j.jrwz.server.clientpackets.C_Attr;
import l1j.jrwz.server.clientpackets.C_AuthLogin;
import l1j.jrwz.server.clientpackets.C_BanClan;
import l1j.jrwz.server.clientpackets.C_BanParty;
import l1j.jrwz.server.clientpackets.C_Board;
import l1j.jrwz.server.clientpackets.C_BoardBack;
import l1j.jrwz.server.clientpackets.C_BoardDelete;
import l1j.jrwz.server.clientpackets.C_BoardRead;
import l1j.jrwz.server.clientpackets.C_BoardWrite;
import l1j.jrwz.server.clientpackets.C_Buddy;
import l1j.jrwz.server.clientpackets.C_CallPlayer;
import l1j.jrwz.server.clientpackets.C_ChangeHeading;
import l1j.jrwz.server.clientpackets.C_ChangeWarTime;
import l1j.jrwz.server.clientpackets.C_CharReset;
import l1j.jrwz.server.clientpackets.C_CharcterConfig;
import l1j.jrwz.server.clientpackets.C_Chat;
import l1j.jrwz.server.clientpackets.C_ChatParty;
import l1j.jrwz.server.clientpackets.C_ChatWhisper;
import l1j.jrwz.server.clientpackets.C_CheckPK;
import l1j.jrwz.server.clientpackets.C_Clan;
import l1j.jrwz.server.clientpackets.C_CommonClick;
import l1j.jrwz.server.clientpackets.C_CreateChar;
import l1j.jrwz.server.clientpackets.C_CreateClan;
import l1j.jrwz.server.clientpackets.C_CreateParty;
import l1j.jrwz.server.clientpackets.C_DelBuddy;
import l1j.jrwz.server.clientpackets.C_DeleteBookmark;
import l1j.jrwz.server.clientpackets.C_DeleteChar;
import l1j.jrwz.server.clientpackets.C_DeleteInventoryItem;
import l1j.jrwz.server.clientpackets.C_Deposit;
import l1j.jrwz.server.clientpackets.C_Door;
import l1j.jrwz.server.clientpackets.C_Drawal;
import l1j.jrwz.server.clientpackets.C_DropItem;
import l1j.jrwz.server.clientpackets.C_Emblem;
import l1j.jrwz.server.clientpackets.C_EnterPortal;
import l1j.jrwz.server.clientpackets.C_Exclude;
import l1j.jrwz.server.clientpackets.C_ExitGhost;
import l1j.jrwz.server.clientpackets.C_ExtraCommand;
import l1j.jrwz.server.clientpackets.C_Fight;
import l1j.jrwz.server.clientpackets.C_FishClick;
import l1j.jrwz.server.clientpackets.C_FixWeaponList;
import l1j.jrwz.server.clientpackets.C_GiveItem;
import l1j.jrwz.server.clientpackets.C_HireSoldier;
import l1j.jrwz.server.clientpackets.C_ItemUSe;
import l1j.jrwz.server.clientpackets.C_JoinClan;
import l1j.jrwz.server.clientpackets.C_KeepALIVE;
import l1j.jrwz.server.clientpackets.C_LeaveClan;
import l1j.jrwz.server.clientpackets.C_LeaveParty;
import l1j.jrwz.server.clientpackets.C_LoginToServer;
import l1j.jrwz.server.clientpackets.C_LoginToServerOK;
import l1j.jrwz.server.clientpackets.C_Mail;
import l1j.jrwz.server.clientpackets.C_MoveChar;
import l1j.jrwz.server.clientpackets.C_NPCAction;
import l1j.jrwz.server.clientpackets.C_NPCTalk;
import l1j.jrwz.server.clientpackets.C_NewCharSelect;
import l1j.jrwz.server.clientpackets.C_Party;
import l1j.jrwz.server.clientpackets.C_PetMenu;
import l1j.jrwz.server.clientpackets.C_PickUpItem;
import l1j.jrwz.server.clientpackets.C_Pledge;
import l1j.jrwz.server.clientpackets.C_Propose;
import l1j.jrwz.server.clientpackets.C_QuitGame;
import l1j.jrwz.server.clientpackets.C_Rank;
import l1j.jrwz.server.clientpackets.C_Restart;
import l1j.jrwz.server.clientpackets.C_Result;
import l1j.jrwz.server.clientpackets.C_ReturnToLogin;
import l1j.jrwz.server.clientpackets.C_SelectList;
import l1j.jrwz.server.clientpackets.C_SelectTarget;
import l1j.jrwz.server.clientpackets.C_SendLocation;
import l1j.jrwz.server.clientpackets.C_ServerVersion;
import l1j.jrwz.server.clientpackets.C_Ship;
import l1j.jrwz.server.clientpackets.C_Shop;
import l1j.jrwz.server.clientpackets.C_ShopList;
import l1j.jrwz.server.clientpackets.C_SkillBuy;
import l1j.jrwz.server.clientpackets.C_SkillBuyOK;
import l1j.jrwz.server.clientpackets.C_TaxRate;
import l1j.jrwz.server.clientpackets.C_Teleport;
import l1j.jrwz.server.clientpackets.C_Title;
import l1j.jrwz.server.clientpackets.C_Trade;
import l1j.jrwz.server.clientpackets.C_TradeAddItem;
import l1j.jrwz.server.clientpackets.C_TradeCancel;
import l1j.jrwz.server.clientpackets.C_TradeOK;
import l1j.jrwz.server.clientpackets.C_UsePetItem;
import l1j.jrwz.server.clientpackets.C_UseSkill;
import l1j.jrwz.server.clientpackets.C_War;
import l1j.jrwz.server.clientpackets.C_Who;
import l1j.jrwz.server.clientpackets.ClientBasePacket;
import l1j.jrwz.server.model.Instance.L1PcInstance;

// Referenced classes of package l1j.jrwz.server:
// Opcodes, LoginController, ClientThread, Logins

/**
 * 封包处理程序.
 */
public class PacketHandler {

    private static Logger _log = Logger
            .getLogger(PacketHandler.class.getName());
    /** 客户端封包集合. */
    private static final Map<Integer, ClientBasePacket> OP_LIST = new HashMap<Integer, ClientBasePacket>();
    private final ClientThread _client;

    /**
     * 封包处理程序.
     * 
     * @param client
     *            - 客户端对象
     */
    public PacketHandler(ClientThread client) {
        _client = client;
    }

    /**
     * 处理客户端封包.
     * 
     * @param abyte0
     *            - 资料
     * @param object
     *            - 无用
     * @throws Exception
     *             构造详细消息为 null 的新异常
     */
    public void handlePacket(byte[] abyte0, L1PcInstance object)
            throws Exception {
        ClientBasePacket basePacket = null;
        if (abyte0 == null) {
            return;
        }
        if (abyte0.length <= 0) {
            return;
        }
        try {
            int i = abyte0[0] & 0xff;
            basePacket = OP_LIST.get(i);
            if (basePacket == null) {
                _log.warning("收到客户端传来的未知封包：" + i);
                return;
            } else {
                basePacket.execute(abyte0, _client);
            }
        } catch (final Exception e) {
            _log.log(Level.SEVERE, e.getLocalizedMessage(), e);
        } finally {
            basePacket = null;
        }
    }

    // 静态块
    static {
        put(C_OPCODE_BOOKMARK, new C_AddBookmark()); // 请求 增加记忆坐标
        put(C_OPCODE_BOOKMARKDELETE, new C_DeleteBookmark()); // 请求 删除记忆坐标
        put(C_OPCODE_CHATGLOBAL, new C_Chat()); // 请求 使用广播聊天频道
        put(C_OPCODE_CHATWHISPER, new C_ChatWhisper()); // 请求 使用密语聊天频道
        put(C_OPCODE_CHAT, new C_Chat()); // 请求 使用一般聊天频道
        put(C_OPCODE_EXCLUDE, new C_Exclude()); // 请求 使用拒绝名单(开启指定人物讯息)
        put(C_OPCODE_TITLE, new C_Title()); // 请求 赋予封号(/title)
        put(C_OPCODE_CREATECLAN, new C_CreateClan()); // 请求 创立血盟
        put(C_OPCODE_JOINCLAN, new C_JoinClan()); // 请求 加入血盟
        put(C_OPCODE_LEAVECLANE, new C_LeaveClan()); // 请求 脱离血盟
        put(C_OPCODE_BANCLAN, new C_BanClan()); // 请求 驱逐血盟成员
        put(C_OPCODE_RANK, new C_Rank()); // 请求 给予角色血盟阶级(例：/rank 人物 见习)
        put(C_OPCODE_PLEDGE, new C_Pledge()); // 请求 查询血盟成员
        put(C_OPCODE_EMBLEM, new C_Emblem()); // 请求 上传盟徽
        put(C_OPCODE_CLAN, new C_Clan()); // 请求 更新血盟数据(例如盟标)
        put(C_OPCODE_WAR, new C_War()); // 请求 宣战/投降/停战
        put(C_OPCODE_TAXRATE, new C_TaxRate()); // 请求 变更领地税率
        put(C_OPCODE_CHANGEWARTIME, new C_ChangeWarTime()); // 请求 决定下次围城时间(官方已取消使用)
        put(C_OPCODE_COMMONCLICK, new C_CommonClick()); // 请求 下一步(伺服器公告视窗后 显示角色列表)
        put(C_OPCODE_NEWCHAR, new C_CreateChar()); // 请求 创造角色
        put(C_OPCODE_CHANGECHAR, new C_NewCharSelect()); // 请求 切换角色
        put(C_OPCODE_DELETECHAR, new C_DeleteChar()); // 请求 删除角色
        put(C_OPCODE_CHANGEHEADING, new C_ChangeHeading()); // 请求 改变角色面向
        put(C_OPCODE_MOVECHAR, new C_MoveChar()); // 请求 移动角色
        put(C_OPCODE_ATTACK, new C_Attack()); // 请求 角色攻击
        put(C_OPCODE_ARROWATTACK, new C_Attack()); // 请求 使用远程攻击
        put(C_OPCODE_EXTCOMMAND, new C_ExtraCommand()); // 请求 角色表情动作
        put(C_OPCODE_CHARRESET, new C_CharReset()); // 请求 重置角色属性点
        put(C_OPCODE_BOARDWRITE, new C_BoardWrite()); // 请求 写入新的布告栏讯息
        put(C_OPCODE_BOARDREAD, new C_BoardRead()); // 请求 阅读单个布告栏内容
        put(C_OPCODE_BOARD, new C_Board()); // 请求 读取 布告栏/拍卖公告 讯息列表(浏览布告栏)
        put(C_OPCODE_BOARDNEXT, new C_BoardBack()); // 请求 查看下一页布告栏讯息
        put(C_OPCODE_BOARDDELETE, new C_BoardDelete()); // 请求 删除布告栏内容
        put(C_OPCODE_USEITEM, new C_ItemUSe()); // 请求 使用物品
        put(C_OPCODE_USESKILL, new C_UseSkill()); // 请求 使用技能
        put(C_OPCODE_USEPETITEM, new C_UsePetItem()); // 请求 使用宠物装备
        put(C_OPCODE_CREATEPARTY, new C_CreateParty()); // 请求 邀请加入队伍/创立队伍
        put(C_OPCODE_PARTYLIST, new C_Party()); // 请求 查询队伍成员名单
        put(C_OPCODE_CAHTPARTY, new C_ChatParty()); // 请求 聊天队伍对话控制(/chatparty)
        put(C_OPCODE_BANPARTY, new C_BanParty()); // 请求 踢出队伍
        put(C_OPCODE_LEAVEPARTY, new C_LeaveParty()); // 请求 脱离队伍
        put(C_OPCODE_ENTERPORTAL, new C_EnterPortal()); // 请求 传送 (进入地监)
        put(C_OPCODE_AMOUNT, new C_Amount()); // 请求 物件对话视窗数量选取结果
        put(C_OPCODE_FIX_WEAPON_LIST, new C_FixWeaponList()); // 请求 查询损坏的道具(维修物品清单)
        put(C_OPCODE_SELECTLIST, new C_SelectList()); // 请求 修理损坏的道具
        put(C_OPCODE_EXIT_GHOST, new C_ExitGhost()); // 请求 退出幽灵模式(观看模式)
        put(C_OPCODE_CALL, new C_CallPlayer()); // 请求 执行线上人物列表命令(GM管理选单)传送至指定的外挂使用者身旁
        put(C_OPCODE_HIRESOLDIER, new C_HireSoldier()); // 请求 雇请佣兵列表(购买佣兵完成)
        put(C_OPCODE_FISHCLICK, new C_FishClick()); // 请求 钓鱼收竿
        put(C_OPCODE_SELECTTARGET, new C_SelectTarget()); // 请求 攻击指定物件(宠物&召唤)
        put(C_OPCODE_PETMENU, new C_PetMenu()); // 请求 宠物回报选单
        put(C_OPCODE_TELEPORT, new C_Teleport()); // 请求 更新周围物件(传送后解除传送锁定)
        put(C_OPCODE_FIGHT, new C_Fight()); // 请求 决斗
        put(C_OPCODE_SHIP, new C_Ship()); // 请求 下船
        put(C_OPCODE_MAIL, new C_Mail()); // 请求 打开邮箱
        put(C_OPCODE_SENDLOCATION, new C_SendLocation()); // 请求 传送位置&视窗失焦
        put(C_OPCODE_DELETEINVENTORYITEM, new C_DeleteInventoryItem()); // 请求 删除物品
        put(C_OPCODE_PICKUPITEM, new C_PickUpItem()); // 请求 捡取物品
        put(C_OPCODE_DROPITEM, new C_DropItem()); // 请求 丢弃物品(丢弃至地面)
        put(C_OPCODE_WHO, new C_Who()); // 请求 查询在线游戏人数(/who)
        put(C_OPCODE_GIVEITEM, new C_GiveItem()); // 请求 给予物品
        put(C_OPCODE_NPCTALK, new C_NPCTalk()); // 请求 物件对话视窗
        put(C_OPCODE_ADDBUDDY, new C_AddBuddy()); // 请求 新增好友
        put(C_OPCODE_DELBUDDY, new C_DelBuddy()); // 请求 删除好友
        put(C_OPCODE_BUDDYLIST, new C_Buddy()); // 请求 查询好友名单
        put(C_OPCODE_CLIENTVERSION, new C_ServerVersion()); // 请求 请求验证客户端版本
        put(C_OPCODE_LOGINPACKET, new C_AuthLogin()); // 请求 登入伺服器
        put(C_OPCODE_RETURNTOLOGIN, new C_ReturnToLogin()); // 请求 回到登入画面
        put(C_OPCODE_LOGINTOSERVER, new C_LoginToServer()); // 请求 进入游戏
        put(C_OPCODE_KEEPALIVE, new C_KeepALIVE()); // 请求 更新时间/连线状态
        put(C_OPCODE_RESTART, new C_Restart()); // 请求 死亡后重新开始
        put(C_OPCODE_SHOP, new C_Shop()); // 请求 开设个人商店
        put(C_OPCODE_PRIVATESHOPLIST, new C_ShopList()); // 请求 购买指定的个人商店商品(商品清单)
        put(C_OPCODE_ATTR, new C_Attr()); // 请求 点选项目的结果(Y/N)
        put(C_OPCODE_RESULT, new C_Result()); // 请求 取得列表中的物品
        put(C_OPCODE_DEPOSIT, new C_Deposit()); // 城堡宝库(请求存入资金)
        put(C_OPCODE_DRAWAL, new C_Drawal()); // 城堡宝库(请求领出资金)
        put(C_OPCODE_LOGINTOSERVEROK, new C_LoginToServerOK()); // 请求 选取观看频道or配置角色设定
        put(C_OPCODE_TRADE, new C_Trade()); // 请求 交易(双方交易)
        put(C_OPCODE_TRADEADDCANCEL, new C_TradeCancel()); // 请求 取消交易(双方交易)
        put(C_OPCODE_TRADEADDITEM, new C_TradeAddItem()); // 请求 增加交易物品(双方交易)
        put(C_OPCODE_TRADEADDOK, new C_TradeOK()); // 请求 完成交易(双方交易)
        put(C_OPCODE_CHECKPK, new C_CheckPK()); // 请求 查询PK次数(/checkpk)
        put(C_OPCODE_PROPOSE, new C_Propose()); // 请求 结婚(/propose)
        put(C_OPCODE_SKILLBUY, new C_SkillBuy()); // 请求 学习魔法清单(金币)
        put(C_OPCODE_SKILLBUYOK, new C_SkillBuyOK()); // 请求 完成学习魔法(金币)
        put(C_OPCODE_CHARACTERCONFIG, new C_CharcterConfig()); // 请求 纪录快捷键
        put(C_OPCODE_DOOR, new C_Door()); // 请求 门的控制(开关)/宝箱的开启
        put(C_OPCODE_NPCACTION, new C_NPCAction()); // 请求 执行物件对话视窗动作/结果
        put(C_OPCODE_QUITGAME, new C_QuitGame()); // 请求 离开游戏 TODO 未实做
    }

    /**
     * 将客户端封包放入集合列表内.
     * 
     * @param key
     *            - 键(封包码)
     * @param value
     *            - 值(类)
     */
    private static void put(final Integer key, final ClientBasePacket value) {
        if (OP_LIST.get(key) == null) {
            OP_LIST.put(key, value);
        } else {
            if (!key.equals(-19)) {
                _log.warning("重复的客户端封包码: " + key + " " + value.getType());
            }
        }
    }
}
